This subroutine implements the method presented by Gonzalez-Longatt et al. (2015). Zonal and meridional components are computed and then orographic correction is applied. The two components are then re-composed to provide final result.
References:
González-Longatt, F., Medina, H., Serrano González, J., Spatial interpolation and orographic correction to estimate wind energy resource in Venezuela. Renewable and Sustainable Energy Reviews, 48, 1-16, 2015.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(ObservationalNetwork), | intent(in) | :: | speed | |||
type(ObservationalNetwork), | intent(in) | :: | dir | |||
type(grid_real), | intent(in) | :: | dem | |||
type(grid_real), | intent(inout) | :: | grid | |||
type(grid_real), | intent(inout), | optional | :: | winddir |
Type | Visibility | Attributes | Name | Initial | |||
---|---|---|---|---|---|---|---|
type(ObservationalNetwork), | public | :: | active_dir | ||||
type(ObservationalNetwork), | public | :: | active_speed | ||||
real(kind=float), | public | :: | cellsize | ||||
real(kind=float), | public | :: | corr1 | ||||
real(kind=float), | public | :: | corr2 | ||||
integer, | public | :: | count_dir | ||||
integer, | public | :: | count_speed | ||||
integer, | public | :: | i | ||||
integer, | public | :: | j | ||||
type(ObservationalNetwork), | public | :: | temp_dir | ||||
type(ObservationalNetwork), | public | :: | temp_speed | ||||
type(ObservationalNetwork), | public | :: | uwind | ||||
type(grid_real), | public | :: | uwind_grid | ||||
logical, | public | :: | validEast | ||||
logical, | public | :: | validNorth | ||||
logical, | public | :: | validSouth | ||||
logical, | public | :: | validWest | ||||
type(ObservationalNetwork), | public | :: | vwind | ||||
type(grid_real), | public | :: | vwind_grid | ||||
real(kind=float), | public | :: | vxcalc | ||||
real(kind=float), | public | :: | vycalc |
SUBROUTINE WindGonzalezLongatt & ! (speed, dir, dem, grid, winddir) USE Units, ONLY: & !Imported parameters degToRad, radToDeg, pi IMPLICIT NONE !Arguments with intent (in): TYPE (ObservationalNetwork), INTENT(IN) :: speed !windspeed observations at stations TYPE (ObservationalNetwork), INTENT(IN) :: dir !wind direction observations at stations TYPE (grid_real), INTENT(IN) :: dem !digital elevation model !Arguments with intent (inout): TYPE (grid_real), INTENT (INOUT) :: grid !wind speed grid [m/s] TYPE (grid_real), OPTIONAL, INTENT (INOUT) :: winddir !wind direction [deg] !Local declarations TYPE (ObservationalNetwork) :: temp_speed, temp_dir, active_speed, active_dir TYPE (ObservationalNetwork) :: uwind, vwind INTEGER :: count_speed, count_dir, i, j TYPE (grid_real) :: uwind_grid !zonal wind [m/s] TYPE (grid_real) :: vwind_grid !meridional wind [m/s] !OK REAL (KIND = float) :: vxcalc !zonal wind with orograpcic correction applied [m/s] REAL (KIND = float) :: vycalc !meridional wind with orograpcic correction applied [m/s] REAL (KIND = float) :: corr1, corr2, cellsize LOGICAL :: validNorth, validSouth, validEast, validWest !----------------end of declarations------------------------------------------- !check for available measurements. Both speed and direction must exist !first check nodata. If only speed or direction are missing, set both to missing ! assume dir and speed stations are in memory in the same order CALL CopyNetwork (speed,temp_speed) CALL CopyNetwork (dir,temp_dir) DO i = 1, temp_speed %countObs IF (temp_speed % obs (i) % value == temp_speed % nodata) THEN !set dir to nodata temp_dir % obs (i) % value = temp_dir % nodata ELSE IF (temp_dir % obs (i) % value == temp_dir % nodata) THEN !set speed to nodata temp_speed % obs (i) % value = temp_speed % nodata END IF END DO !now remove nodata CALL ActualObservations (temp_speed, count_speed, active_speed) CALL ActualObservations (temp_dir, count_dir, active_dir) !initialize zonal and meridional component network CALL CopyNetwork (active_speed, uwind) CALL CopyNetwork (active_speed, vwind) !initialize grid CALL NewGrid (uwind_grid, grid) CALL NewGrid (vwind_grid, grid) !compute u and v at stations DO i = 1, active_speed % countObs uwind % obs (i) % value = - active_speed % obs (i) % value * & SIN ( active_dir % obs (i) % value * degToRad) vwind % obs (i) % value = - active_speed % obs (i) % value * & COS ( active_dir % obs (i) % value * degToRad) END DO !interpolate u and v grid CALL IDW (network=uwind, grid=uwind_grid, method=1, power=2.0, near=5) !CALL BarnesOI (network=uwind, grid=uwind_grid, gammapar = 0.6) CALL IDW (network=vwind, grid=vwind_grid, method=1, power=2.0, near=5) !CALL BarnesOI (network=vwind, grid=vwind_grid, gammapar = 0.6) !apply orographic correction DO i = 1, grid % idim DO j = 1, grid % jdim IF (grid % mat (i,j) /= grid % nodata) THEN !set cellsize cellsize = (CellArea (grid,i,j) ) ** 0.5 ![m] !check for neighbour cells. Nodata and out !of grid cells must not be considered !for orographic correction validNorth = CellIsValid (i-1, j, grid) validSouth = CellIsValid (i+1, j, grid) validEast = CellIsValid (i, j+1, grid) validWest = CellIsValid (i, j-1, grid) !correct zonal (along x) component IF (validEast .AND. validWest) THEN !apply correction where east and west data are defined !west correction factor component corr1 = (dem % mat (i,j) - dem % mat (i,j-1)) * & (uwind_grid % mat (i,j-1) - uwind_grid % mat (i,j) ) / cellsize !east correction factor component corr2 = (dem % mat (i,j+1) - dem % mat (i,j)) * & (uwind_grid % mat (i,j) - uwind_grid % mat (i,j+1) ) / cellsize vxcalc = uwind_grid % mat(i,j) + 0.5 * ( corr1 + corr2) ELSE !do not apply correction vxcalc = uwind_grid % mat(i,j) END IF !correct meridional (along y) component IF (validNorth .AND. validSouth) THEN !apply correction north and south data are defined !south correction factor component corr1 = (dem % mat (i,j) - dem % mat (i+1,j)) * & (vwind_grid % mat (i+1,j) - vwind_grid % mat (i,j) ) / cellsize !north correction factor component corr2 = (dem % mat (i-1,j) - dem % mat (i,j)) * & (vwind_grid % mat (i,j) - vwind_grid % mat (i-1,j) ) / cellsize vycalc = vwind_grid % mat(i,j) + 0.5 * ( corr1 + corr2) ELSE !do not apply correction vycalc = vwind_grid % mat(i,j) END IF !compute wind direction if required IF (PRESENT (winddir)) THEN ! Some compilers do not allow both u and v to be 0.0 in ! the atan2 computation. IF ( ABS(vxcalc ) < 1e-10) vxcalc = 1e-10 winddir % mat (i,j) = ATAN2(vxcalc,vycalc) IF (winddir % mat (i,j) >= pi) THEN winddir % mat (i,j) = winddir % mat (i,j) - pi ELSE winddir % mat (i,j) = winddir % mat (i,j) + pi END IF !convert radians to deg winddir % mat (i,j) = winddir % mat (i,j) * radToDeg ENDIF !windspeed grid % mat (i,j) = SQRT(vxcalc**2. + vycalc**2.) END IF END DO END DO !deallocate memory CALL DestroyNetwork (temp_speed) CALL DestroyNetwork (temp_dir) CALL DestroyNetwork (active_speed) CALL DestroyNetwork (active_dir) CALL DestroyNetwork (uwind) CALL DestroyNetwork (vwind) CALL GridDestroy (uwind_grid) CALL GridDestroy (vwind_grid) RETURN END SUBROUTINE WindGonzalezLongatt